import ij.IJ;
import ij.ImagePlus;
import ij.WindowManager;
import ij.gui.GUI;
import ij.gui.Plot;
import ij.gui.Roi;
import ij.plugin.FFT;
import ij.plugin.frame.*;
import ij.process.ImageProcessor;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.*;
import java.util.Map.Entry;



public class Spectrum_ extends PlugInFrame implements ActionListener {
	public static final String SPECTRUM_COMMAND = "View graphs";
	public static final String RADIAL_SPECTRUM_COMMAND = "RadialSpectrum";
	public static final String DISTANCE_INPUT = "Distance";
	public static final String SPECTRUM = "Spectrum";
	private double spec = Double.NaN;

	private ImagePlus imp;
	private ImageProcessor ip;
	private Panel mainPane;

	private Map<String, TextField> commandFields = new TreeMap<String, TextField>();
	private Map<String, Label> results = new TreeMap<String, Label>();
	private Map<String, TextField> inputs = new TreeMap<String, TextField>();

	public Spectrum_() {
		super("Spectrum Analysis");
		imp = WindowManager.getCurrentImage();
		if (imp == null) {
			IJ.showMessage("No image", "There are no images open.");
			return;
		}

		mainPane = new Panel();

		mainPane.setLayout(new GridLayout(0, 3, 10, 5));
		addResult(SPECTRUM);
		addCommand(SPECTRUM_COMMAND);
		add(mainPane);
		pack();
		setVisible(true);
		GUI.center(this);
	}

	public void run(java.lang.String arg) {
		if (imp == null) {
			return;
		}
		ip = imp.getProcessor();
		Roi roi = imp.getRoi();
	}

	private void addCommand(String labelText, String buttonText, double defaultValue) {
		Label label = new Label(labelText);
		TextField textField = new TextField(String.format("%.0f", defaultValue));
		commandFields.put(buttonText, textField);
		inputs.put(labelText, textField);
		Button button = new Button(buttonText);
		button.addActionListener(this);
		button.setActionCommand(buttonText);
		mainPane.add(label);
		mainPane.add(textField);
		mainPane.add(button);
	}

	private void addNonEditableInput(String labelText, double defaultValue) {
		Label label = new Label(labelText);
		TextField textField = new TextField(String.format("%.0f", defaultValue));
		textField.setEditable(false);
		inputs.put(labelText, textField);
		mainPane.add(label);
		mainPane.add(textField);
		addLabel("");
	}

	private void addResult(String resultName) {
		Label nameLabel = new Label(resultName);
		Label resultLabel = new Label();
		results.put(resultName, resultLabel);
		mainPane.add(nameLabel);
		mainPane.add(resultLabel);
		addLabel("");
	}

	private void addCommand(String buttonText) {
		Button button = new Button(buttonText);
		button.addActionListener(this);
		button.setActionCommand(buttonText);
		addLabel("");
		mainPane.add(button);
		addLabel("");
	}

	private void addLabel(String labelText) {
		mainPane.add(new Label(labelText));
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		imp = WindowManager.getCurrentImage();
		String command = e.getActionCommand();
		if (SPECTRUM_COMMAND.equals(command)){
			FFT fft = new FFT();
			fft.run("");
			ImagePlus specImp = IJ.getImage();
			ImageProcessor specIp = specImp.getProcessor();
			drawRadialSpectrum(specIp);
			results.get(SPECTRUM).setText(format(spec));
		}
	}

	private void drawRadialSpectrum(ImageProcessor ip) {
		imp = WindowManager.getCurrentImage();
		if (imp == null) {
			IJ.showMessage("No image", "There are no images open.");
			return;
		}
		int width = ip.getWidth();
		double[][] results = new double[width / 2][width / 2];
		for (int y = 0; y < width / 2; y++)
			for (int x = 0; x < width / 2; x++) {
					results[x][y] += ip.getPixelValue(width / 2 + x, width / 2 + y);
					results[x][y] += ip.getPixelValue(width / 2 - x - 1, width / 2 + y);
					results[x][y] += ip.getPixelValue(width / 2 + x, width / 2 - y - 1);
					results[x][y] += ip.getPixelValue(width / 2 - x - 1, width / 2 - y - 1);
					results[x][y] /= 4.0;
				}

		for (int y = 0; y < width / 2; y++){
			for (int x = 0; x < width / 2; x++) {
				results[0][y] = 0.0;
				results[x][0] = 0.0;
			}
		}
		
		double[] keys = new double[width / 2];
		double[] values = new double[width / 2];
		double[] counts = new double[width / 2];
		values[0] = 0.0;
		counts[0] = 1.0;
		for (int r = 0; r < width / 2; ++r){
			keys[r] = r;
			for (int loci = 0; loci < width / 2; ++loci)
				for (int locj = 0; locj < width / 2; ++locj) {
					int position = loci * loci + locj * locj;
					if (position <= r * r && position > (r - 1) * (r - 1)) {
						values[r] += results[loci][locj];
						counts[r] += 1.0;
					}
				}
		}
		double maxV = 0.0;
		for (int r = 0; r < width / 2; ++r){
			values[r] /= counts[r];
			if (values[r] > maxV){
				maxV = values[r];
				spec = keys[r];
			}
			
		}
		Plot plot = new Plot("Radial Spectrum", "Distance", "Power", keys, values);
		plot.show();
	}
	
	
	private String format(double d) {
		return String.format("%f", d);
	}

}